package com.yang.auth.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.yang.auth.constant.RedisKeyConstant;
import com.yang.auth.constant.RoleConstant;
import com.yang.auth.dao.UserDao;
import com.yang.auth.dao.UserRoleRelDao;
import com.yang.auth.enums.LoginTypeEnum;
import com.yang.auth.model.entity.User;
import com.yang.auth.model.entity.UserRoleRel;
import com.yang.auth.model.vo.user.UserLoginReqVo;
import com.yang.auth.service.IUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Objects;

/**
* @author 30793
* @description 针对表【t_user(用户测试表)】的数据库操作Service实现
* @createDate 2024-08-06 14:38:19
*/
@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Resource
    private UserServiceImpl currentProxy;
    @Resource
    private UserDao userDao;
    @Resource
    private UserRoleRelDao userRoleRelDao;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private TransactionTemplate transactionTemplate;    //  手动操作事务


    @Override
    public String loginAndRegister(UserLoginReqVo userLoginReqVo) {

        String phone = userLoginReqVo.getPhone();
        Integer type = userLoginReqVo.getType();
        //  获取登录类型的枚举值
        LoginTypeEnum loginTypeEnum = LoginTypeEnum.valueOf(type);
        //  判断登录类型，验证码登录、账号密码登录
        switch (loginTypeEnum) {
            case VERIFICATION_CODE -> {
                String code = userLoginReqVo.getCode();
                //  1.校验验证码     利用断言校验参数
                Assert.notBlank(code, "验证码错误");
                //  2.从redis中获取验证码与之对比
                String verificationCodeKey = RedisKeyConstant.getVerificationCodeKey(phone);
                String redisCode = (String) redisTemplate.opsForValue().get(verificationCodeKey);
                //      利用断言校验两验证码是否一致
                Assert.equals(code, redisCode, "验证码错误");
                //  3.判断用户是否需要注册
                User user = userDao.selectByPhone(phone);
                if (Objects.isNull(user)) {
                    //  利用代理对象调用事务方法，可以避免事务失效
//                    user = currentProxy.register(phone);
                    user = register(phone);
                }
                //  4.使用用户id进行登录
                StpUtil.login(user.getId());
            }
            case PASSWORD -> {
                //  todo: 账号密码登录

            }
            default -> {

            }
        }
        //  返回token
        return StpUtil.getTokenValue();
    }

    @Override
    public void logout() {
        //  todo:   退出登录
        StpUtil.logout();
    }

    //    @Transactional(rollbackFor = Exception.class)
    public User register(String phone) {
        /**
         * 通过TransactionTemplate操作事务
         */
        return transactionTemplate.execute(transactionStatus -> {
            User user = null;
            try {
                //  根据全局唯一id生成器生成小红书id账号
                Long littleRedBookId = redisTemplate.opsForValue().increment(RedisKeyConstant.getLittleRedBookIdGeneratorKey());
                //  添加用户
                user = User.builder()
                        .nickname(RandomUtil.randomString("小红书用户",16))
                        .phone(phone)
                        .littleRedBookId(String.valueOf(littleRedBookId))
                        .build();
                userDao.save(user);

                //  给用户分配角色
                UserRoleRel userRoleRel = UserRoleRel.builder()
                        .userId(user.getId())
                        .roleId(RoleConstant.COMMON_USER_ROLE_ID)
                        .build();
                userRoleRelDao.save(userRoleRel);

                //  将用户角色id存入redis
                String userRoleKey = RedisKeyConstant.getUserRoleKey(phone);
                redisTemplate.opsForSet().add(userRoleKey, RoleConstant.COMMON_USER_ROLE_ID);

                log.info("用户注册成功，手机号：{}，用户信息：{}", phone, JSONUtil.toJsonStr(user));
            } catch (Exception e) {
                //  事务回滚
                transactionStatus.setRollbackOnly();
                throw new RuntimeException(e);
            } finally {
                return user;
            }
        });

    }


}




